﻿using System;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;

namespace JQMergeFramework
{
    public class MainCityControl : MonoBehaviour
    {
        public static MainCityControl I;
        
        public BhvEasyPool mainCityPool;
        
        [Header("房子放置平台模型")] public MeshRenderer cityPlatformMesh;
        [Header("棋盘模型")] public MeshRenderer chessboardMesh;
        
        private List<MainCityUnit> showList = new List<MainCityUnit>();
        private Mesh[] mMeshList;
        
        //房子节点高度
        private float[] cityNodeHeightAry;
        //房子的平台高度
        public float cityPlatformHeight;
        //棋盘模型大小
        public Vector3 chessboardSize;

        private Bounds mBounds;
        
      
        //最低展示10个房子
        private int minShowNum = 10;
        private void Awake()
        {
            I = this;
            
            float f = CommonFun.GetScreenRatio();
            mBounds = new Bounds(Vector3.zero, new Vector3(0, 570*f, 0));
            mMeshList = MergeManager.Instance.scriptablePrefab.mainCityMeshList;
            
            cityPlatformHeight = cityPlatformMesh.bounds.size.y;
            chessboardSize = chessboardMesh.bounds.size;

            
            cityNodeHeightAry = new float[mMeshList.Length];
            for (int i = 0; i < mMeshList.Length; i++)
            {
                cityNodeHeightAry[i] = mMeshList[i].bounds.size.y;
            }

            InitMainCity();
        }


        void InitMainCity()
        {
            List<int> idList  = DataManager.Instance.BuildCityIdList;
            //生成房子节点
            for (int i = 0; i < idList.Count; i++)
            {
                if (i < minShowNum)
                {
                    MainCityUnit nodeGo = mainCityPool.Get().GetComponent<MainCityUnit>();
                    int index = idList[i];
                    Mesh mesh = mMeshList[index];
                    Vector3 pos = new Vector3(0, GetCityNodeHeight(i-1, false), 0);
                    nodeGo.SetMesh(i,mesh, pos);
                    showList.Add(nodeGo);
                }
            }
        }


        //升高楼层
        public void PlayBuildTheHouse(List<int> newIdList)
        {
            //关闭棋盘
         
             CityBaseControl.I.SetShowChessboard(false);
             MergeManager manager = MergeManager.Instance;
            
             Sequence sq = DOTween.Sequence();
             
             
             int alreadyBuildCount = DataManager.Instance.BuildCityIdList.Count;
             int tempIndex = -1;
             //生成房子节点
             for (int i =  alreadyBuildCount -newIdList.Count; i < alreadyBuildCount; i++)
             {
                 tempIndex++;
                 MainCityUnit mainCityUnit = mainCityPool.Get().GetComponent<MainCityUnit>();
                 Mesh mesh = manager.scriptablePrefab.mainCityMeshList[newIdList[tempIndex]];
                 Vector3 pos = new Vector3(0, MainCityControl.I.GetCityNodeHeight(i-1, false), 0);
                 mainCityUnit.SetMesh(i,mesh, new Vector3(0, pos.y + 200, 0));
                 showList.Add(mainCityUnit);
                 mainCityUnit.SetShow(false);
                 sq.AppendInterval(0.2F);
                 sq.AppendCallback(() =>
                 {
                     mainCityUnit.SetShow(true);
                     AudioManager.Instance.Play(AudioName.PassCityDown);
                     // mainCityUnit.mAudioCtrl.Play(AudioName.PassCityDown,1F);
                 });
                 sq.Append(mainCityUnit.transform.DOMoveY(pos.y, 0.5f).OnComplete(() =>
                 {
                     mainCityUnit.PlaySmoke();
                 }).SetEase(Ease.OutExpo));
             }
            
             sq.OnComplete(() =>
             {
                 MergeManager.Instance.isPlayNewMainCity = false;
                 
                 UIManager.Instance.GetWindow<UIAddLvTips>().Open(BuildTipsType.BuildFinish);
             });
             sq.Play();
        }
        

        /// <summary>
        /// 更新坐标
        /// </summary>
        public void UpdatePos()
        {
            if (showList.Count <= 0 || MergeManager.Instance.isPlayNewMainCity)
            {
                return;
            }
            
            for (int i = showList.Count-1; i >= 0; --i)
            {
                if (!ObjectVisible(showList[i].transform.position.y))
                {
                    ReleaseItem(showList[i]);
                    showList.RemoveAt(i);
                }
            }
            
            
            int index = showList[0].mIndex - 1;
            int afterIndex = showList[showList.Count - 1].mIndex + 1;
            
            while (index >= 0)
            {
                float height = GetCityNodeHeight(index-1,false);
                int idx = DataManager.Instance.BuildCityIdList[index];
                if (!ObjectVisible(height))
                    break;
                showList.Insert(0, ShowItem(index,new Vector3(0,height,0)));
                index--;
            }
            
            while (afterIndex < DataManager.Instance.BuildCityIdList.Count)
            {
                float height = GetCityNodeHeight(afterIndex-1,false);
                int idx = DataManager.Instance.BuildCityIdList[afterIndex];
                if (!ObjectVisible(height))
                    break;
                showList.Add(ShowItem(afterIndex,new Vector3(0,height,0)));
                afterIndex++;
            }
        }

        void ReleaseItem(MainCityUnit unit)
        {
            mainCityPool.Put(unit.gameObject);
        }

        MainCityUnit ShowItem(int idx,Vector3 pos)
        {
            int id = DataManager.Instance.BuildCityIdList[idx];
            MainCityUnit item =  mainCityPool.Get().GetComponent<MainCityUnit>();
            item.SetMesh(idx,mMeshList[id],pos);
            return item;
        }

        #region 获取房子的高度
        //获取房子节点的总高度
        public float GetCityNodeHeight(bool isAddChessboardHeight = true)
        {
            float addHeight = 0;
            
            List<int> idList = DataManager.Instance.BuildCityIdList;
            for (int i = 0; i < idList.Count; i++)
            {
                addHeight += cityNodeHeightAry[idList[i]];
            }
            
            if (isAddChessboardHeight)
            {
                return cityPlatformHeight + addHeight + chessboardSize.y;
            }
            else
            {
                return cityPlatformHeight + addHeight;
            }
        }
        
        //获取房子的总高度
        public float GetCityNodeHeight(int index, bool isAddChessboardHeight = true)
        {
            float addHeight = 0;
            
            List<int> idList = DataManager.Instance.BuildCityIdList;
            for (int i = 0; i < idList.Count; i++)
            {
                if (i > index) break;
                addHeight += cityNodeHeightAry[idList[i]];
            }
            
            if (isAddChessboardHeight)
            {
                return cityPlatformHeight + addHeight + chessboardSize.y;
            }
            else
            {
                return cityPlatformHeight + addHeight;
            }
        }
        #endregion


        
        //判断是否在视野内
        public bool ObjectVisible(float height)
        {
            //bounds 优化 重新计算
            //GeometryUtility.TestPlanesAABB()方法，该方法可以检测一个AABB包围盒（即物体的边界框）是否在视锥体内，
            //返回一个bool值。如果返回值为true，则表示物体在视锥体内；如果返回值为false，则表示物体不在视锥体内。
       
            // 排序：[0] = 左、[1] = 右、[2] = 下、[3] = 上、[4] = 近、[5] = 远
            // Plane[] mPlane = GeometryUtility.CalculateFrustumPlanes(GameCameraControl.I.mCamera);

            mBounds.center = new Vector3(0, GameCameraControl.I.GetOffsetCameraPosY, 0);

            if (height > mBounds.center.y-mBounds.extents.y && height < mBounds.center.y+mBounds.extents.y)
            {
                return true;
            }
            return false;
            // return mBounds.Contains(point);
        }
        
 
        
        //保存成就
        public bool IsNewAchievementFinish()
        {
            //保存成就
            int alreadyBuildCount = DataManager.Instance.BuildCityIdList.Count;
      
            CityTargetCfg cfg = TableConfig.Instance.GetFinishedTargetCfg(alreadyBuildCount);
            //成就完成进度
            if (cfg!=null && cfg.lv > DataManager.Instance.AchievementFinishIndex)
            {
                DataManager.Instance.AchievementFinishIndex = cfg.lv;
                return true;
            }
            return false;
        }

        
        //保存新增楼层的id
        public List<int> SaveAddBuildId()
        {
            List<int> idList = GetNewBuildIDList();
            DataManager.Instance.AddBuildRange(idList);
            return idList;
        }

        
        //获取新盖楼层id
        private List<int> GetNewBuildIDList()
        {
            List<int> idList = new List<int>();
            
            NumericalCfg numericalCfg = TableConfig.Instance.GetNumericalCfg(DataManager.Instance.Lv);
            int alreadyBuildCount = DataManager.Instance.BuildCityIdList.Count;
            for (int i = alreadyBuildCount; i < alreadyBuildCount + numericalCfg.addCityNum; i++)
            {
                int index = GetMainCityIndex(i);
                idList.Add(index);
            }
            return idList;
        }
        
        
        public int GetMainCityIndex(int index)
        {
            if (index == 0)
            {
                return 0;
            }
            int startIndex = GetCurrentMainCityNode(index);
            startIndex = startIndex >= 5 ? startIndex % 5 : startIndex;
            int mod = index % 40;
            
            //两个一组
            //0,底座
            //1，2，2，2，2
            //1，1，1，1，1....2
            //1,2,1,2,1,2...
            //1,1,1,1,1,...2
            //1,1,1,1,1....2
            //40层更换一次
            int showId = 0;
            switch (startIndex)
            {
                case 0:
                    //5个一组
                    //1，2，2，2，2
                    showId = mod % 5 == 1 ? 1 : 2;
                    break;
                case 1:
                    //1，1，1，1，1....2
                    showId = mod  == 0? 4 : 3;
                    break;
                case 2:
                    //1,2,1,2,1,2...
                    showId = mod % 2 == 0 ? 6 : 5;
                    break;
                case 3:
                    //1,1,1,1,1,...2
                    showId = mod  == 0 ? 8 : 7;
                    break;
                case 4:
                    //1,1,1,1,1....2
                    showId = mod  == 0 ? 10 : 9;
                    break;
            }
            return showId;
        }
        
        //获取楼层节点
        private int GetCurrentMainCityNode(int index)
        {
            if (index == 0)
            {
                return 0;
            }
            int startIndex = Mathf.FloorToInt((index-1)/40.0F);
            startIndex = startIndex >= 5 ? startIndex % 5 : startIndex;
            return startIndex;
        }


    }
}